﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Services.Providers;
using System.Web.Hosting;
using System.IO;
using System.Data.Services;
using System.Data.Objects;

namespace FilmBook.DataServices.PhotoStream
{
    public class PhotoStreamProvider : IDataServiceStreamProvider, IDisposable
    {
        private FilmBookEntities dataContext;
        private Photo cachedEntity;
        private string storePath;
        private string tempFilename;
        
        public PhotoStreamProvider(FilmBookEntities context)
        {
            dataContext = context;
            storePath = HostingEnvironment.MapPath("~/App_Data/");
            tempFilename = Path.GetTempFileName();
        }

        #region [ IDataServicesStreamProvider Members ]

        public void DeleteStream(object entity, DataServiceOperationContext operationContext)
        {
            if (entity == null)
                throw new DataServiceException(500, "DeleteStream Entity Object was NULL");

            try
            {
                File.Delete(Path.Combine(storePath, "image" + (entity as Photo).ID));
            }
            catch (IOException ioe)
            {
                throw new DataServiceException("The image temp file could not be found.", ioe);
            }
        }

        public Stream GetReadStream(object entity, string etag, 
            bool? checkETagForEquality, 
            DataServiceOperationContext operationContext)
        {
            if (checkETagForEquality.HasValue)
                throw new DataServiceException(400, "ETag Header Not Supported");

            if (entity == null)
                throw new DataServiceException(500, "GetReadStream Entity Object was NULL");

            string fullPath = Path.Combine(storePath, "image" + (entity as Photo).ID);
            if (!File.Exists(fullPath))
                throw new DataServiceException(500, "The image temp file could not be found.");

            return new FileStream(fullPath, FileMode.Open);
        }

        public Uri GetReadStreamUri(object entity, DataServiceOperationContext operationContext)
        {
            return null;
        }

        public string GetStreamContentType(object entity, DataServiceOperationContext operationContext)
        {
            if (entity == null)
                throw new DataServiceException(500, "GetStreamContentType Entity Object was NULL");

            return (entity as Photo).FileType.ToString();
        }

        public string GetStreamETag(object entity, DataServiceOperationContext operationContext)
        {
            return null;
        }

        public Stream GetWriteStream(object entity, string etag, 
            bool? checkETagForEquality, 
            DataServiceOperationContext operationContext)
        {
            if (checkETagForEquality.HasValue)
                throw new DataServiceException(500, "ETag Write Not Supported");

            Photo img = entity as Photo;
            if (img == null)
                throw new DataServiceException(500, "GetWriteStream Entity Object was NULL");

            if (operationContext.RequestMethod == "POST")
            {
                cachedEntity = img;
                return new FileStream(tempFilename, FileMode.Open);
            }
            else
            {
                return new FileStream(Path.Combine(storePath, "image" + img.ID), 
                    FileMode.Open, FileAccess.Write);
            }
        }

        public string ResolveType(string entitySetName, DataServiceOperationContext operationContext)
        {
            if (entitySetName == "Photos" || entitySetName == "Photo")
                return "FilmBook.DataServices.Photo";
            else
                return null;
        }

        public int StreamBufferSize
        {
            get { return 128000; }
        }

        #endregion

        #region [ IDisposable Members ]

        public void Dispose()
        {
            if (cachedEntity != null)
            {
                ObjectStateEntry entry = dataContext.ObjectStateManager
                    .GetObjectStateEntry(cachedEntity);
                if (entry.State == System.Data.EntityState.Unchanged)
                {
                    File.Move(tempFilename, Path.Combine(storePath, "image" + cachedEntity.ID));
                    File.Delete(tempFilename);
                }
                else
                {
                    dataContext.DeleteObject(cachedEntity);
                    File.Delete(tempFilename);

                    throw new DataServiceException("An error occurred. The photo could not be save.");
                }
            }
        }

        #endregion
    }
}
